/* * Copyright (C) 2014 Mark Clarke * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package za.co.jumpingbean.gcexplorer.ui; import za.co.jumpingbean.utils.Units; import java.io.IOException; import java.net.URL; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Arrays; import java.util.ResourceBundle; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.StackedBarChart; import javafx.scene.chart.XYChart; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.util.converter.NumberStringConverter; /** * * @author mark */ public class ProcessViewForm implements Initializable { @FXML private LineChart<Number, Number> chtEdenSpace; @FXML private LineChart<Number, Number> chtSurvivorSpace; @FXML private LineChart<Number, Number> chtOldGenSpace; @FXML private LineChart<Number, Number> chtPermGenSpace; @FXML private Button btnGenerateGarbageOptions; @FXML private TextArea lblSysInfo; @FXML private Label lblGCInfo; @FXML private TextArea txtGeneratorStatus; private final GCExplorer app; private final UUID procId; @FXML private StackedBarChart<String, Number> chtStackedBarTotalMemory; @FXML private CategoryAxis xAxisCategory; @FXML private HBox hBox; @FXML private GridPane gridPane; @FXML private StackedAreaChart<Number, Number> chtStackedAreaTotalMemory; @FXML private Button btnViewGCLog; private Stage gcViewForm; public ProcessViewForm(GCExplorer app, UUID procId) { this.procId = procId; this.app = app; } @Override public void initialize(URL location, ResourceBundle resources) { configureChart(chtEdenSpace); configureChart(chtSurvivorSpace); configureChart(chtOldGenSpace); configureChart(chtPermGenSpace); configureChart(chtStackedAreaTotalMemory); chtEdenSpace.setData(app.getProcessController().getEdenSeries(procId)); chtSurvivorSpace.setData(app.getProcessController().getSurvivorSeries(procId)); chtOldGenSpace.setData(app.getProcessController().getOldGenSeries(procId)); chtPermGenSpace.setData(app.getProcessController().getPermGenSeries(procId)); ((NumberAxis) chtStackedAreaTotalMemory.getYAxis()).setForceZeroInRange(true); chtStackedAreaTotalMemory.setData(app.getProcessController().getStackedAreaChartSeries(procId)); this.xAxisCategory.setCategories(FXCollections.<String>observableArrayList(Arrays.asList("Total"))); this.chtStackedBarTotalMemory.setData(app.getProcessController().getStackedBarChartSeries(procId)); configureChart(chtStackedBarTotalMemory); HBox.setHgrow(gridPane, Priority.ALWAYS); ((NumberAxis) this.chtStackedBarTotalMemory.getYAxis()).setTickLabelFormatter(new NumberStringConverter(NumberFormat.getIntegerInstance())); this.updateYAxii(app.getUnits()); btnGenerateGarbageOptions.setOnAction(this::showGarbageOptionsForm); app.getProcessController().addSystemInfoEventListener(procId, new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { if (oldValue == null || !oldValue.equals(newValue)) { Platform.runLater(new Runnable() { @Override public void run() { lblSysInfo.setText(newValue); } }); } } }); btnViewGCLog.setOnAction(this::showGCLogView); app.getProcessController().addGCInfoEventListener(procId, new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { if (oldValue == null || !oldValue.equals(newValue)) { Platform.runLater(new Runnable() { @Override public void run() { lblGCInfo.setText(newValue); } }); } } }); lblSysInfo.setText("Updating..."); lblGCInfo.setText("Updating..."); } public void disableGenerateObjectsButton() { this.btnGenerateGarbageOptions.disableProperty().setValue(Boolean.TRUE); this.txtGeneratorStatus.disableProperty().setValue(Boolean.TRUE); } private void showGCLogView(ActionEvent e) { if (gcViewForm != null) { gcViewForm.toFront(); return; } gcViewForm = new Stage(); try { FXMLLoader loader = new FXMLLoader( getClass().getResource("gcLogView.fxml") ); GCLogViewForm controller = new GCLogViewForm(app, procId,this); loader.setController(controller); Parent pane = loader.load(); Scene scene = new Scene(pane); gcViewForm.setScene(scene); gcViewForm.initModality(Modality.NONE); gcViewForm.initOwner(gridPane.getParent().getScene().getWindow()); gcViewForm.initStyle(StageStyle.DECORATED); gcViewForm.setTitle(app.getProcessController().getProcName(procId)); gcViewForm.setOnCloseRequest(controller); gcViewForm.show(); } catch (IOException ex) { Logger.getLogger(ProcessViewForm.class.getName()).log(Level.SEVERE, null, ex); } } private void showGarbageOptionsForm(ActionEvent e) { Stage stage = new Stage(); try { FXMLLoader loader = new FXMLLoader( getClass().getResource("garbageGeneratorOptionsForm.fxml") ); GarbageGenerationOptionsForm controller = new GarbageGenerationOptionsForm(app, procId, this); loader.setController(controller); Parent pane = loader.load(); Scene scene = new Scene(pane); stage.setScene(scene); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(gridPane.getParent().getScene().getWindow()); stage.initStyle(StageStyle.UTILITY); stage.show(); } catch (IOException ex) { Logger.getLogger(ProcessViewForm.class.getName()).log(Level.SEVERE, null, ex); } } private void configureChart(XYChart chart) { chart.setAnimated(false); chart.getXAxis().setAnimated(false); chart.getXAxis().setAutoRanging(true); if (chart.getXAxis() instanceof NumberAxis) { ((NumberAxis) chart.getXAxis()).setForceZeroInRange(false); ((NumberAxis) chart.getXAxis()).setTickLabelFormatter(new NumberStringConverter(NumberFormat.getIntegerInstance())); } chart.getYAxis().setAnimated(false); chart.getYAxis().setAutoRanging(true); ((NumberAxis) chart.getYAxis()).setForceZeroInRange(false); ((NumberAxis) chart.getYAxis()).setTickLabelFormatter(new NumberStringConverter(new DecimalFormat("#,###,##0.000"))); } void updateYAxii(Units unit) { chtEdenSpace.getYAxis().setLabel(unit.getName()); chtSurvivorSpace.getYAxis().setLabel(unit.getName()); chtOldGenSpace.getYAxis().setLabel(unit.getName()); chtPermGenSpace.getYAxis().setLabel(unit.getName()); chtStackedBarTotalMemory.getYAxis().setLabel(unit.getName()); chtStackedAreaTotalMemory.getYAxis().setLabel(unit.getName()); } public void setGenStatus(String str) { Platform.runLater(new Runnable() { @Override public void run() { synchronized (app) { txtGeneratorStatus.setText(str); } } }); } void resetGCLogView() { this.gcViewForm=null; } }